using System;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;

using EF;

namespace EF.Features.FeatureEFWorkflowTimer
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>

    [Guid("e962ec53-ea69-4e9b-9662-244fc501ca19")]
    public class FeatureEFWorkflowTimerEventReceiver : SPFeatureReceiver
    {
        public void logDebug(string strMessage)
        {
            EFWorkflowTimer.logTraceInfo(strMessage);
        }

        //public void logDebugHistory(SPWeb objSPWeb, string strMessage)
        //{
        //    EFWorkflowTimer.logDebugHistory(objSPWeb, strMessage, this.GetType().Assembly);
        //}

        // Uncomment the method below to handle the event raised after a feature has been activated.
        public void initLists(SPSite objSPSite)
        {
            SPList splistConfiguration = null;
            SPView oViewConfiguration = null;
            SPViewFieldCollection oViewFieldsConfiguration = null;
            Guid guidConfiguration = Guid.Empty;

            SPList splistHistory = null;
            SPView oViewHistory = null;
            SPViewFieldCollection oViewFieldsHistory = null;
            Guid guidHistory = Guid.Empty;

            SPList splistJob = null;
            SPView oViewJob = null;
            SPViewFieldCollection oViewFieldsJob = null;
            Guid guidJob = Guid.Empty;

            string strViewQuery = string.Empty;
            string strViewQueryTemplate = string.Empty;
            StringCollection viewFields = null;

            try
            {
                splistJob = objSPSite.RootWeb.Lists.TryGetList(EFWorkflowTimer.Job_ListTitle);
                if (splistJob != null)
                    splistJob.Delete();
                //if (splistJob == null)
                {
                    guidJob = objSPSite.RootWeb.Lists.Add(EFWorkflowTimer.Job_ListTitle, EFWorkflowTimer.Job_ListDescription, SPListTemplateType.GenericList);
                    splistJob = objSPSite.RootWeb.Lists[guidJob];

                    splistJob.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerJob_AdminLink, SPFieldType.URL, false);

                    splistJob.EnableAttachments = false;
                    splistJob.Update();

                    oViewJob = splistJob.DefaultView;
                    oViewFieldsJob = oViewJob.ViewFields;
                    oViewFieldsJob.Add(splistJob.Fields[EFWorkflowTimer.Column_EFWorkflowTimerJob_AdminLink]);
                    oViewJob.Update();

                    viewFields = new StringCollection();
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerJob_AdminLink);

                    oViewJob =splistJob.Views.Add(EFWorkflowTimer.View_Portal, viewFields, strViewQuery, 30, true, false);
                    oViewJob.TabularView = false;
                    oViewJob.Update();
                }

                splistConfiguration = objSPSite.RootWeb.Lists.TryGetList(EFWorkflowTimer.Configuration_ListTitle);
                if (splistConfiguration != null)
                    splistConfiguration.Delete();
                //if (splistConfiguration == null)
                {
                    guidConfiguration = objSPSite.RootWeb.Lists.Add(EFWorkflowTimer.Configuration_ListTitle, EFWorkflowTimer.Configuration_ListDescription, SPListTemplateType.GenericList);
                    splistConfiguration = objSPSite.RootWeb.Lists[guidConfiguration];

                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType, SPFieldType.Choice, true);
                    SPFieldChoice objSPFieldWorkflowType = (SPFieldChoice)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType];
                    objSPFieldWorkflowType.Choices.Add(EFWorkflowTimer.WorkflowType_Site);
                    objSPFieldWorkflowType.Choices.Add(EFWorkflowTimer.WorkflowType_List);
                    objSPFieldWorkflowType.DefaultValue = EFWorkflowTimer.WorkflowType_Site;
                    objSPFieldWorkflowType.Update();

                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType, SPFieldType.Choice, true);
                    SPFieldChoice objSPFieldRecurringType = (SPFieldChoice)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType];
                    objSPFieldRecurringType.Choices.Add(EFWorkflowTimer.RecurringType_Monthly);
                    objSPFieldRecurringType.Choices.Add(EFWorkflowTimer.RecurringType_Weekly);
                    objSPFieldRecurringType.Choices.Add(EFWorkflowTimer.RecurringType_Daily);
                    objSPFieldRecurringType.Choices.Add(EFWorkflowTimer.RecurringType_Hourly);
                    objSPFieldRecurringType.Choices.Add(EFWorkflowTimer.RecurringType_Minutes);
                    objSPFieldRecurringType.DefaultValue = EFWorkflowTimer.RecurringType_Daily;
                    objSPFieldRecurringType.Update();

                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName, SPFieldType.Text, true);
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WebUrl, SPFieldType.Text, false);
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl, SPFieldType.Text, false);
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_TraceHistory, SPFieldType.Boolean, false);
                    SPFieldBoolean objSPFieldTraceHistory = (SPFieldBoolean)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_TraceHistory];
                    objSPFieldTraceHistory.DefaultValue = "1";
                    objSPFieldTraceHistory.Update();

                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime, SPFieldType.DateTime, false);
                    SPFieldDateTime objSPFieldLastScanTime = (SPFieldDateTime)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime];
                    objSPFieldLastScanTime.DisplayFormat = SPDateTimeFieldFormatType.DateTime;
                    objSPFieldLastScanTime.Update();

                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanCount, SPFieldType.Number, false);
                    //splistConfiguration.Fields[SPBuiltInFieldId.Title].Required = false;
                    //splistConfiguration.Fields[SPBuiltInFieldId.Title].Update();


                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_BussinessHourOnly, SPFieldType.Boolean, true);
                    SPFieldBoolean objSPFieldBussinessHourOnly = (SPFieldBoolean)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_BussinessHourOnly];
                    objSPFieldBussinessHourOnly.DefaultValue = @"0";
                    objSPFieldBussinessHourOnly.Update();

                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_IsActive, SPFieldType.Boolean, true);
                    SPFieldBoolean objSPFieldIsActive = (SPFieldBoolean)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_IsActive];
                    objSPFieldIsActive.DefaultValue = @"1";
                    objSPFieldIsActive.Update();

                    splistConfiguration.EnableAttachments = false;
                    splistConfiguration.Update();

                    oViewConfiguration = splistConfiguration.DefaultView;
                    oViewFieldsConfiguration = oViewConfiguration.ViewFields;
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WebUrl]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_TraceHistory]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_BussinessHourOnly]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_IsActive]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanCount]);
                    oViewConfiguration.TabularView = false;
                    oViewConfiguration.Update();

                    viewFields = new StringCollection();
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WebUrl);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_TraceHistory);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_BussinessHourOnly);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_IsActive);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime);
                    viewFields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanCount);

                    strViewQueryTemplate = @"<Eq><FieldRef Name='" + EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType + @"' /><Value Type='Choice'>{0}</Value></Eq>";
                    strViewQueryTemplate += @"<Eq><FieldRef Name='IsActive' /><Value Type='Boolean'>1</Value></Eq>";
                    strViewQueryTemplate = @"<Where><And>" + strViewQueryTemplate + @"</And></Where>";
                    strViewQuery = string.Format(strViewQueryTemplate, EFWorkflowTimer.RecurringType_Monthly);
                    splistConfiguration.Views.Add(EFWorkflowTimer.RecurringType_Monthly, viewFields, strViewQuery, 30, true, false);
                    strViewQuery = string.Format(strViewQueryTemplate, EFWorkflowTimer.RecurringType_Weekly);
                    splistConfiguration.Views.Add(EFWorkflowTimer.RecurringType_Weekly, viewFields, strViewQuery, 30, true, false);
                    strViewQuery = string.Format(strViewQueryTemplate, EFWorkflowTimer.RecurringType_Daily);
                    splistConfiguration.Views.Add(EFWorkflowTimer.RecurringType_Daily, viewFields, strViewQuery, 30, true, false);
                    strViewQuery = string.Format(strViewQueryTemplate, EFWorkflowTimer.RecurringType_Hourly);
                    splistConfiguration.Views.Add(EFWorkflowTimer.RecurringType_Hourly, viewFields, strViewQuery, 30, true, false);
                    strViewQuery = string.Format(strViewQueryTemplate, EFWorkflowTimer.RecurringType_Minutes);
                    splistConfiguration.Views.Add(EFWorkflowTimer.RecurringType_Minutes, viewFields, strViewQuery, 30, true, false);

                    //add test data
                    SPListItem itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"test site workflow 1";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType] = EFWorkflowTimer.RecurringType_Daily;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_Site;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"SiteWorkflow1";
                    itemConfiguration.Update();

                    itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"test site workflow 2";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType] = EFWorkflowTimer.RecurringType_Hourly;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_Site;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"SiteWorkflow1";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WebUrl] = @"Subsite1/Subsite2";
                    itemConfiguration.Update();

                    itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"test list workflow 1";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType] = EFWorkflowTimer.RecurringType_Daily;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_List;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"ListWorkflow1";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl] = @"Lists/testTimer/AllItems.aspx";
                    itemConfiguration.Update();

                    itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"test list workflow 2";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType] = EFWorkflowTimer.RecurringType_Monthly;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_List;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"ListWorkflow2";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WebUrl] = @"subsite1";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl] = @"Lists/testTimer/AllItems.aspx";
                    itemConfiguration.Update();

                    itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"test list workflow 3";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_RecurringType] = EFWorkflowTimer.RecurringType_Weekly;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_List;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"ListWorkflow2";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WebUrl] = @"Subsite1/Subsite2";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl] = @"DocumentLib1/Forms/testView.aspx";
                    itemConfiguration.Update();
                }

                //make sure the history list is already created
                splistHistory = objSPSite.RootWeb.Lists.TryGetList(EFWorkflowTimer.History_ListTitle);
                if (splistHistory != null)
                    splistHistory.Delete();

                guidHistory = objSPSite.RootWeb.Lists.Add(EFWorkflowTimer.History_ListTitle, EFWorkflowTimer.History_ListDescription, SPListTemplateType.GenericList);
                splistHistory = objSPSite.RootWeb.Lists[guidHistory];
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebTitle, SPFieldType.Note, false);
                SPFieldMultiLineText objSPFieldWebTitle = (SPFieldMultiLineText)splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebTitle];
                objSPFieldWebTitle.RichText = false;
                objSPFieldWebTitle.RichTextMode = SPRichTextMode.Compatible;
                objSPFieldWebTitle.Update();
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebUrl, SPFieldType.Text, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_ListTitle, SPFieldType.Text, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_Message, SPFieldType.Text, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_ItemId, SPFieldType.Number, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_ItemUrl, SPFieldType.Text, false);
                splistHistory.Fields[SPBuiltInFieldId.Title].Required = false;
                splistHistory.Fields[SPBuiltInFieldId.Title].Update();
                splistHistory.EnableAttachments = false;
                splistHistory.Update();

                oViewHistory = splistHistory.DefaultView;
                oViewFieldsHistory = oViewHistory.ViewFields;
                oViewFieldsHistory.Add(splistHistory.Fields[SPBuiltInFieldId.Modified].InternalName);
                oViewFieldsHistory.Delete(splistHistory.Fields[SPBuiltInFieldId.LinkTitle].InternalName);
                oViewFieldsHistory.Add(splistHistory.Fields[SPBuiltInFieldId.Title].InternalName);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebTitle]);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_ListTitle]);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_Message]);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_ItemUrl]);
                oViewHistory.Query = @"<OrderBy><FieldRef Name='ID' Ascending='FALSE' /></OrderBy>";
                //oViewHistory.TabularView = false;
                oViewHistory.Update();
            }
            catch (Exception ex)
            {
                logDebug(string.Format(@"ex.Message={0}", ex.Message));
                logDebug(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        public void initAdminPage(SPSite objSPSite)
        {
            SPDocumentLibrary spDocPageLib = null;

            SPWeb objSPWeb = objSPSite.RootWeb;
            Guid guidSitePages = Guid.Empty;
            SPList objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.DocLib_SitePages_Title);
            if (objSPList == null)
            {
                guidSitePages = objSPWeb.Lists.Add(EFWorkflowTimer.DocLib_SitePages_PathName, "", SPListTemplateType.DocumentLibrary);
                objSPList = objSPWeb.Lists[guidSitePages];
                objSPList.Title = EFWorkflowTimer.DocLib_SitePages_Title;
                objSPList.Update();
            }
            else
            {
                guidSitePages = objSPList.ID;
                foreach (SPListItem item in objSPList.Items)
                {
                    if (item.File.Name.StartsWith(EFWorkflowTimer.AdminPage_Name, StringComparison.InvariantCultureIgnoreCase))
                    {
                        item.Delete();
                        break;
                    }
                }
            }
            spDocPageLib = (SPDocumentLibrary)objSPWeb.Lists[guidSitePages];

            string strPageUrl = AddWebPartPage(EFWorkflowTimer.AdminPage_Name, "EF WorkflowTimer Admin Page", objSPWeb, spDocPageLib, 2, "WebPartPage", "");

            //string strListUrl = string.Empty;
            ListViewWebPart objListViewWebPart = null;

            try
            {
                objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.Configuration_ListTitle);
                if (objSPList == null)
                    throw new ArgumentException("Configuration List(" + EFWorkflowTimer.Configuration_ListTitle + ") not found.");
                objListViewWebPart = AddListViewToPage(objSPWeb, strPageUrl, objSPList.DefaultView, EFWorkflowTimer.Zone_LeftColumn, 1, @"Scheduled Workflow list");
                EFWorkflowTimer.SetToolbarTypeFreeForm(objSPWeb, strPageUrl, objListViewWebPart.StorageKey);

                objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.History_ListTitle);
                if (objSPList == null)
                    throw new ArgumentException("History List(" + EFWorkflowTimer.History_ListTitle + ") not found.");
                objListViewWebPart = AddListViewToPage(objSPWeb, strPageUrl, objSPList.DefaultView, EFWorkflowTimer.Zone_Footer, 1, @"Workflow running history");

                objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.Job_ListTitle);
                if (objSPList == null)
                    throw new ArgumentException("Job List(" + EFWorkflowTimer.Job_ListTitle + ") not found.");
                //logDebugHistory(string.Format(@"JobView.Title={0}, JobView.Url={1}", objSPList.Views[EFWorkflowTimer.View_Portal].Title, objSPList.Views[EFWorkflowTimer.View_Portal].Url));

                objListViewWebPart = AddListViewToPage(objSPWeb, strPageUrl, objSPList.Views[EFWorkflowTimer.View_Portal], EFWorkflowTimer.Zone_RightColumn, 1, @"Timer jobs settings");
            }
            catch (Exception ex)
            {
                logDebug(string.Format(@"ex.Message={0}", ex.Message));
                logDebug(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        public void initJobs(SPSite objSPSite)
        {
            string strJobName = string.Empty;
            string strJobUrl = string.Empty;
            SPList splistJob = objSPSite.RootWeb.Lists.TryGetList(EFWorkflowTimer.Job_ListTitle);
            SPListItem objSPListItemJob = null;
            EFWorkflowTimer listLoggerJob = null;

            string[] strArrayRecurringType = { EFWorkflowTimer.RecurringType_Monthly, EFWorkflowTimer.RecurringType_Weekly, EFWorkflowTimer.RecurringType_Daily, EFWorkflowTimer.RecurringType_Hourly, EFWorkflowTimer.RecurringType_Minutes };
            try
            {
                foreach (string strRecurringType in strArrayRecurringType)
                {
                    strJobName = EFWorkflowTimer.getFullJobName(objSPSite.Url, strRecurringType);

                    // make sure the job isn't already registered
                    foreach (SPJobDefinition job in objSPSite.WebApplication.JobDefinitions)
                    {
                        //if (job.Name.StartsWith(EFWorkflowTimer.JOB_NAME, StringComparison.InvariantCultureIgnoreCase))
                        if (job.Name.Equals(strJobName, StringComparison.InvariantCultureIgnoreCase))
                            job.Delete();
                    }

                    listLoggerJob = new EFWorkflowTimer(strJobName, objSPSite.WebApplication);

                    switch (strRecurringType)
                    {
                        case EFWorkflowTimer.RecurringType_Monthly:
                            SPMonthlyByDaySchedule scheduleMonthly = new SPMonthlyByDaySchedule();
                            scheduleMonthly.BeginWeek = WeekOfMonth.First;
                            scheduleMonthly.BeginDay = DayOfWeek.Monday;
                            scheduleMonthly.BeginHour = 1;
                            scheduleMonthly.BeginMinute = 0;
                            listLoggerJob.Schedule = scheduleMonthly;
                            break;
                        case EFWorkflowTimer.RecurringType_Weekly:
                            SPWeeklySchedule scheduleWeekly = new SPWeeklySchedule();
                            scheduleWeekly.BeginDayOfWeek = DayOfWeek.Monday;
                            scheduleWeekly.BeginHour = 0;
                            scheduleWeekly.BeginMinute = 0;
                            scheduleWeekly.EndDayOfWeek = DayOfWeek.Monday;
                            scheduleWeekly.EndHour = 1;
                            scheduleWeekly.EndMinute = 59;
                            listLoggerJob.Schedule = scheduleWeekly;
                            break;
                        case EFWorkflowTimer.RecurringType_Daily:
                            SPDailySchedule scheduleDaily = new SPDailySchedule();
                            scheduleDaily.BeginHour = 0;
                            scheduleDaily.EndHour = 1;
                            listLoggerJob.Schedule = scheduleDaily;
                            break;
                        case EFWorkflowTimer.RecurringType_Hourly:
                            SPHourlySchedule scheduleHourly = new SPHourlySchedule();
                            scheduleHourly.BeginMinute = 0;
                            scheduleHourly.EndMinute = 10;
                            listLoggerJob.Schedule = scheduleHourly;
                            break;
                        case EFWorkflowTimer.RecurringType_Minutes:
                            SPMinuteSchedule scheduleMinutes = new SPMinuteSchedule();
                            scheduleMinutes.Interval = 10;
                            listLoggerJob.Schedule = scheduleMinutes;
                            break;
                        default:
                            logDebug(string.Format(@"initJobs(), invalid strRecurringType={0}, strJobName={1}", strRecurringType, strJobName));
                            break;
                    }

                    listLoggerJob.Properties.Add("site-id", objSPSite.ID);
                    listLoggerJob.Properties.Add("web-id", objSPSite.RootWeb.ID);
                    listLoggerJob.Update(true);

                    if (splistJob != null)
                    {
                        objSPListItemJob = splistJob.AddItem();
                        objSPListItemJob[SPBuiltInFieldId.Title] = strJobName;
                        //   http://hvsp2010a:9000/_admin/JobEdit.aspx?JobId=c936e330%2D54a7%2D4314%2D9a68%2D3178934638dc
                        Microsoft.SharePoint.Administration.SPAdministrationWebApplication centralWebApp = SPAdministrationWebApplication.Local;
                        strJobUrl = string.Format("{0}/_admin/JobEdit.aspx?JobId={1}&Source={2}", centralWebApp.Sites[0].Url, listLoggerJob.Id, SPEncode.UrlEncode(objSPSite.Url + @"/" + EFWorkflowTimer.AdminPage_Url));
                        //logDebugHistory(string.Format(@"strJobName={0}, JobUrl={1}", strJobName, strJobUrl));
                        objSPListItemJob[EFWorkflowTimer.Column_EFWorkflowTimerJob_AdminLink] = string.Format("{0}, {1}", strJobUrl, strRecurringType);
                        objSPListItemJob.Update();
                    }
                }

                logDebug(@"Job (" + strJobName + ") created.");
            }
            catch (Exception ex)
            {
                logDebug(string.Format(@"ex.Message={0}", ex.Message));
                logDebug(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        // http://jasear.wordpress.com/2009/04/05/webpartpages-programmatically-adding-a-new-web-part-page/
        // http://msdn.microsoft.com/en-us/library/ms450826.aspx
        //WebPartPage templates you can specify:

        //1, Full Page, Vertical
        //2, Header, Footer, 3 Columns
        //3, Header, Left Column, Body
        //4, Header, Right Column, Body
        //5, Header, Footer, 2 Columns, 4 Rows
        //6, Header, Footer, 4 Columns, Top Row
        //7, Left Column, Header, Footer, Top Row, 3 Columns
        //8, Right Column, Header, Footer, Top Row, 3 Columns

        //Type could have the following possible values:

        //WebPartPage
        //BasicPage
        public string AddWebPartPage(string strFileName, string strFileTitle, SPWeb objSPWeb, SPList objSPList, int iWebPartPageTemplate, string strPageType, string strFolderPath)
        {
            SPFile objSPFile = null;
            string postInformation =
            @"<?xml version=""1.0"" encoding=""UTF-8""?>" +
            @"<Method>" +
            @"<SetList Scope=""Request"">" + objSPList.ID + @"</SetList>" +
            @"<SetVar Name=""ID"">New</SetVar>" +
            @"<SetVar Name=""Cmd"">NewWebPage</SetVar>" +
            @"<SetVar Name=""Type"">" + strPageType + @"</SetVar>" +
            @"<SetVar Name=""WebPartPageTemplate"">" + iWebPartPageTemplate + @"</SetVar>" +
            @"<SetVar Name=""Title"">" + strFileName + @"</SetVar>" +
            @"<SetVar Name=""Overwrite"">true</SetVar>" +
            @"</Method>";
            string processBatch = objSPWeb.ProcessBatchData(postInformation);
            if (processBatch.Equals("<Result ID=\"\" Code=\"0\">\r\n</Result>\n", StringComparison.InvariantCultureIgnoreCase))
            {
                string strFileUrl = objSPList.RootFolder.Url + "/" + strFileName;
                if (strFileUrl.EndsWith(".aspx") == false)
                {
                    strFileUrl += ".aspx";
                }
                objSPFile = objSPWeb.GetFile(strFileUrl);
                //if page was in subfolder then move it there
                if (!String.IsNullOrEmpty(strFolderPath))
                {
                    objSPFile.MoveTo(strFileTitle, true);
                }
                SPFolder rootFolder = objSPFile.ParentFolder;

                using (SPLimitedWebPartManager spLimitedWebPartManager = objSPWeb.GetLimitedWebPartManager(strFileUrl, PersonalizationScope.Shared))
                {

                    foreach (System.Web.UI.WebControls.WebParts.WebPart objWebpart in spLimitedWebPartManager.WebParts)
                    {
                        if (objWebpart.ToString() == "Microsoft.SharePoint.WebPartPages.TitleBarWebPart")
                        {
                            TitleBarWebPart objTitleBarWebPart = (TitleBarWebPart)objWebpart;
                            objTitleBarWebPart.HeaderTitle = strFileTitle;
                            spLimitedWebPartManager.SaveChanges(objTitleBarWebPart);
                            break;
                        }
                    }
                    //System.Web.UI.WebControls.WebParts.WebPart objWebPart = spLimitedWebPartManager.WebParts["TitleBar"];
                    //objWebPart.Title = strFileTitle;
                    objSPWeb.Update();
                }

                return objSPFile.Url;
            }

            return string.Empty;
        }

        public static ListViewWebPart AddListViewToPage(
            SPWeb objSPWeb,
            string pageUrl,
            SPView objSPView,
            string zoneID,
            int zoneIndex,
            string strWebPartTitle)
        {
            ListViewWebPart objListViewWebPart = null;
            string strListUrl = string.Empty;
            string strListViewWebPartID = string.Empty;
            if (string.IsNullOrEmpty(strWebPartTitle))
                strWebPartTitle = objSPView.ParentList.Title;

            using (SPLimitedWebPartManager spLimitedWebPartManager = objSPWeb.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                using (objListViewWebPart = new ListViewWebPart())
                {
                    objListViewWebPart.ListName = objSPView.ParentList.ID.ToString("B").ToUpperInvariant();
                    objListViewWebPart.TitleUrl = objSPView.ServerRelativeUrl;
                    objListViewWebPart.WebId = objSPWeb.ID;
                    objListViewWebPart.Title = strWebPartTitle;
                    objListViewWebPart.ViewGuid = objSPView.ID.ToString();
                    //objListViewWebPart.DisplayTitle = "abcdefg";

                    spLimitedWebPartManager.AddWebPart(objListViewWebPart, zoneID, zoneIndex);
                    strListViewWebPartID = objListViewWebPart.ID;
                }

                //return strListViewWebPartID;
                return objListViewWebPart;
            }
        }

        private System.Web.UI.WebControls.WebParts.WebPart CreateWebPart(SPWeb web, string webPartName)
        {
            SPQuery query = new SPQuery();
            query.Query = String.Format(
                "<Where><Eq><FieldRef Name='FileLeafRef'/><Value Type='File'>{0}</Value></Eq></Where>",
                webPartName);

            SPList webPartGallery = null;

            if (null == web.ParentWeb)
            {
                // This is the root web.
                webPartGallery = web.GetCatalog(SPListTemplateType.WebPartCatalog);
            }
            else
            {
                // This is a sub-web.
                webPartGallery = web.ParentWeb.GetCatalog(SPListTemplateType.WebPartCatalog);
            }

            SPListItemCollection webParts = webPartGallery.GetItems(query);

            string typeName = webParts[0].GetFormattedValue("WebPartTypeName");
            string assemblyName = webParts[0].GetFormattedValue("WebPartAssembly");
            ObjectHandle webPartHandle = Activator.CreateInstance(assemblyName, typeName);

            System.Web.UI.WebControls.WebParts.WebPart webPart =
                (System.Web.UI.WebControls.WebParts.WebPart)webPartHandle.Unwrap();
            return webPart;
        }

        public object ConvertValue(string propertyValue, PropertyInfo property)
        {
            if (propertyValue != string.Empty)
            {
                object value = Convert.ChangeType(propertyValue, property.PropertyType);
                return value;
            }

            return null;
        }

        public void SetWebPartProperty(
            SPWeb web,
            string pageUrl,
            string webPartID,
            string propertyName,
            string propertyValue)
        {
            using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                System.Web.UI.WebControls.WebParts.WebPart part = manager.WebParts[webPartID];
                Type runtimeType = part.GetType();
                PropertyInfo property = runtimeType.GetProperty(propertyName);
                object value = ConvertValue(propertyValue, property);
                property.SetValue(part, value, null);
                manager.SaveChanges(part);
            }
        }

        public void AddWebPartConnection(
            SPWeb web,
            string pageUrl,
            string providerWebPartID,
            string consumerWebPartID,
            string providerConnectionPointName,
            string consumerConnectionPointName)
        {
            using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                System.Web.UI.WebControls.WebParts.WebPart provider = manager.WebParts[providerWebPartID];
                System.Web.UI.WebControls.WebParts.WebPart consumer = manager.WebParts[consumerWebPartID];

                ProviderConnectionPointCollection providerPoints = manager.GetProviderConnectionPoints(provider);
                ConsumerConnectionPointCollection consumerPoints = manager.GetConsumerConnectionPoints(consumer);

                ProviderConnectionPoint providerPoint = null;

                foreach (ProviderConnectionPoint point in providerPoints)
                {
                    if (String.Equals(providerConnectionPointName, point.DisplayName, StringComparison.OrdinalIgnoreCase))
                    {
                        providerPoint = point;
                        break;
                    }
                }

                ConsumerConnectionPoint consumerPoint = null;

                foreach (ConsumerConnectionPoint point in consumerPoints)
                {
                    if (String.Equals(consumerConnectionPointName, point.DisplayName, StringComparison.OrdinalIgnoreCase))
                    {
                        consumerPoint = point;
                        break;
                    }
                }

                manager.SPConnectWebParts(provider, providerPoint, consumer, consumerPoint);
            }
        }

        public void SetRemoteAdministratorAccessDenied(bool boolFlag)
        {
            //SPWebService myService = SPWebService.ContentService; 
            //myService.RemoteAdministratorAccessDenied = false; 
            //myService.Update(); 
        }

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;

            //SPSecurity.RunWithElevatedPrivileges(delegate()
            //{
                using (SPSite objSPSite = new SPSite(site.ID))
                {
                    using (SPWeb objSPWeb = objSPSite.RootWeb)
                    {
                        try
                        {
                            objSPWeb.AllowUnsafeUpdates = true;
                            objSPWeb.Update();

                            SetRemoteAdministratorAccessDenied(false);

                            initLists(objSPSite);
                            initJobs(objSPSite);
                            initAdminPage(objSPSite);
                        }
                        catch (Exception ex)
                        {   
                            logDebug(string.Format(@"ex.Message={0}", ex.Message));
                            logDebug(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
                            throw new SPException(string.Format("The feature could not be activated. ex.Message={0}", ex.Message));
                        }
                        finally
                        {
                            SetRemoteAdministratorAccessDenied(true);

                            objSPWeb.AllowUnsafeUpdates = false;
                            objSPWeb.Update();

                        }
                    }
                }
            //});
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            SPList splistHistory = null;
            SPList splistJob = null;
            string strWebTitle = string.Empty;
            string strJobName = string.Empty;

            //SPSecurity.RunWithElevatedPrivileges(delegate()
            //{
                using (SPSite objSPSite = new SPSite(site.ID))
                {
                    using (SPWeb objSPWeb = objSPSite.RootWeb)
                    {
                        try
                        {
                            SetRemoteAdministratorAccessDenied(false);

                            //delete jobs
                            strWebTitle = objSPWeb.Title;
                            strJobName = EFWorkflowTimer.getFullJobName(objSPSite.Url);
                            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
                            {
                                if (job.Name.StartsWith(strJobName, StringComparison.InvariantCultureIgnoreCase))
                                    job.Delete();
                            }

                            //delete lists
                            splistHistory = objSPWeb.Lists.TryGetList(EFWorkflowTimer.History_ListTitle);
                            if (splistHistory != null)
                                splistHistory.Delete();

                            splistJob = objSPSite.RootWeb.Lists.TryGetList(EFWorkflowTimer.Job_ListTitle);
                            if (splistJob != null)
                                splistJob.Delete();

                            //delete admin page
                            Guid guidSitePages = Guid.Empty;
                            SPList objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.DocLib_SitePages_Title);
                            if (objSPList != null)
                            {
                                guidSitePages = objSPList.ID;
                                foreach (SPListItem item in objSPList.Items)
                                {
                                    if (item.File.Name.StartsWith(EFWorkflowTimer.AdminPage_Name, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        item.Delete();
                                        break;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logDebug(string.Format(@"ex.Message={0}", ex.Message));
                            logDebug(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
                            throw new SPException("The feature could not be deactivated.");
                        }
                        finally
                        {
                            SetRemoteAdministratorAccessDenied(true);
                        }

                        //logDebugHistory(@"Feature deactivated. Job (" + strJobName + ") deleted.");
                    }
                }
            //});
        }

        // Uncomment the method below to handle the event raised after a feature has been installed.

        //public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        //{
        //}


        // Uncomment the method below to handle the event raised before a feature is uninstalled.

        //public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        //{
        //}

        // Uncomment the method below to handle the event raised when a feature is upgrading.

        //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        //{
        //}
    }
}
